package com.custom.action.model;

import com.custom.action.condition.ConditionWrapper;
import com.custom.action.condition.Conditions;
import com.custom.action.condition.DefaultConditionWrapper;
import com.custom.action.condition.LambdaConditionWrapper;
import com.custom.action.core.TableInfoCache;
import com.custom.action.core.TableParseModel;
import com.custom.action.interfaces.TableExecutor;
import com.custom.comm.utils.Converts;
import com.custom.comm.exceptions.CustomCheckException;
import com.custom.comm.utils.ReflectUtil;

import java.io.Serializable;
import java.util.function.Consumer;

/**
 ActiveRecord装配模式的父类，继承该类即可获得crud功能
 * @param <T> 实体对象类型
 * @param <P> 主键类型
 * @author   Xiao-Bai
 * @since  2022/7/15 0015 14:47
 *
 */
@SuppressWarnings("unchecked")
public abstract class ActiveBaseModel<T, P extends Serializable> implements BaseModelHandler, Serializable {


    /**
     * 删除此记录
     */
    public final boolean delete() throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        P primaryKeyValue = tableExecutor.primaryKeyValue((T) this);
        if (primaryKeyValue == null) {
            throw new CustomCheckException("Value of primary key not specified");
        }
        return Converts.toBool(tableExecutor.deleteByKey(primaryKeyValue));
    }

    /**
     * 根据主键修改
     */
    public final boolean update() throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        return Converts.toBool(tableExecutor.updateByKey((T) this));
    }

    /**
     * 根据主键是否为空自行插入或修改一条记录
     */
    public final boolean save() throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        return Converts.toBool(tableExecutor.save((T) this));
    }

    /**
     * 插入一条记录
     */
    public final boolean insert() throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        if (tableExecutor.primaryKeyValue((T) this) != null) {
            return false;
        }
        return Converts.toBool(tableExecutor.insert((T) this));
    }


    public final void selectKeySet() throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        P keyValue = tableExecutor.primaryKeyValue((T) this);
        selectKeySet(keyValue);
    }

    public final void selectKeySet(P key) throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        final P keyValue = key != null ? key : tableExecutor.primaryKeyValue((T) this);
        if (keyValue == null) {
            return;
        }
        tableExecutor.selectByKey(keyValue, (T) this);
    }

    public final void injection(ConditionWrapper<T> wrapper) throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        tableExecutor.selectOne(wrapper, (T) this);
    }

    public final void injection(Consumer<DefaultConditionWrapper<T>> consumer) throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        DefaultConditionWrapper<T> query = Conditions.query(target());
        consumer.accept(query);
        tableExecutor.selectOne(query, (T) this);
    }

    public final void injectionEx(Consumer<LambdaConditionWrapper<T>> consumer) throws Exception {
        TableExecutor<T, P> tableExecutor = thisExecutor();
        LambdaConditionWrapper<T> query = Conditions.lambdaQuery(target());
        consumer.accept(query);
        tableExecutor.selectOne(query, (T) this);
    }


    /**
     * 获取表操作对象
     */
    private TableExecutor<T, P> thisExecutor() {
        TableParseModel<T> tableModel = (TableParseModel<T>) TableInfoCache.getTableModel(this.getClass());
        return TableInfoCache.getTableExecutor(tableModel.getOrder(), target());
    }

    private Class<T> target() {
       return ReflectUtil.getThisGenericType(this.getClass());
    }

    public void insertBefore() {

    }


    public void updateBefore() {

    }

    public void queryAfter() {

    }

}
